package pl.ydp.ivy.flex.ide;

import java.io.File;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.ivy.core.module.descriptor.Artifact;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;

import pl.ydp.ivy.IRetrieveMonitor;

import com.adobe.flexbuilder.project.ClassPathEntryFactory;
import com.adobe.flexbuilder.project.IClassPathEntry;
import com.adobe.flexbuilder.project.IFlexLibraryProject;
import com.adobe.flexbuilder.project.IFlexProject;
import com.adobe.flexbuilder.project.actionscript.ActionScriptCore;
import com.adobe.flexbuilder.project.actionscript.IActionScriptProject;
import com.adobe.flexbuilder.project.actionscript.IMutableActionScriptProjectSettings;

public class ProjectIvyFilter implements IRetrieveMonitor {

	IProject baseProject;
	WorkspaceIvyProjects ivyProjects;
	Set<File> badArtifacts = new HashSet<File>();
	Set<IProject> referencedProjects = new HashSet<IProject>();


	public ProjectIvyFilter(IProject baseProject,
			WorkspaceIvyProjects ivyProjects) {
		this.baseProject = baseProject;
		this.ivyProjects = ivyProjects;
	}
	
	public void retrieved(Artifact artifact, File destFile) {
		IProject artifactProject = ivyProjects.findProject(
			artifact.getModuleRevisionId() );
		if ( artifactProject!=null && artifactProject.isAccessible() ) {
			IActionScriptProject asProject = ActionScriptCore.getProject( artifactProject );
			if (asProject instanceof IFlexLibraryProject) {
				badArtifacts.add( destFile );
				referencedProjects.add( artifactProject );
			}
		}
	}
	
	public void doFilter( IProgressMonitor monitor ) throws CoreException {
		for( File artifact: badArtifacts ) {
			artifact.delete();
		}

		IActionScriptProject baseAsProject = ActionScriptCore.getProject( baseProject );
		
		IMutableActionScriptProjectSettings settings = baseAsProject.getProjectSettingsClone();
		IClassPathEntry [] libEntries = settings.getLibraryPath();
		
		Map<String, IProject> name2project = new HashMap<String, IProject>();
		for( IProject pr: referencedProjects )
			name2project.put( pr.getName(), pr );
		
		// remove projects already referenced
		for( IClassPathEntry entry: libEntries ) {
			if ( entry.getKind()==IClassPathEntry.KIND_LIBRARY_FILE ) {
				String pPath = entry.getValue();
				if ( pPath.startsWith("/" ) ) {
					String prjName = pPath.substring( 1, pPath.indexOf('/', 1) );
					name2project.remove( prjName );
				}
			}
		}
		
		if ( !name2project.isEmpty() ) {
			IClassPathEntry [] nLibEntries = new IClassPathEntry[libEntries.length+name2project.size()];
			System.arraycopy( libEntries, 0, nLibEntries, 0, libEntries.length );
			int nextIndex = libEntries.length;
			libEntries = nLibEntries;
			
			for( IProject referencedProject: name2project.values() ) {
				IFlexLibraryProject asProject = (IFlexLibraryProject) ActionScriptCore.getProject( referencedProject );
				
				IFile swcFile = asProject.getOutputDebugSWCFile();
				
				URI refProjectLocation = referencedProject.getLocation().makeAbsolute().toFile().toURI();
				URI swcLocation = swcFile.getRawLocationURI();
				String prjPath = "/"+referencedProject.getName()+"/"+
					refProjectLocation.relativize( swcLocation ).toString();
	
				IClassPathEntry prjEntry = ClassPathEntryFactory.newEntry( IClassPathEntry.KIND_LIBRARY_FILE, prjPath, settings );
				if ( baseAsProject instanceof IFlexProject )
					prjEntry.setLinkType( IClassPathEntry.LINK_TYPE_INTERNAL );
				else
					prjEntry.setLinkType( IClassPathEntry.LINK_TYPE_EXTERNAL );
				
				libEntries[nextIndex] = prjEntry;
				++nextIndex;
			}
	
			settings.setLibraryPath( libEntries );
			baseAsProject.setProjectDescription( settings, monitor );
		}
	}
}
